﻿using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using SunXNA.RainbowXNA.Batch;

namespace SunXNA.RainbowXNA.RenderObject
{
    class CPlaneRenderObject : IBaseRenderObject
    {
        #region Public Types
        #endregion

        #region Private Member Variables

        private VertexPositionNormalTexture[] m_vertices;
        private int[] m_indexes;

        private VertexDeclaration m_vertexDeclaration;
        private VertexBuffer m_vertexBuffer;
        private IndexBuffer m_indexBuffer;

        private BoundingSphere m_graphicsVolume;
        private BoundingBox m_boundingBox;

        #endregion

        #region Protected Member Variables
        #endregion

        #region Puplic Member Properties

        public BoundingSphere Volume
        {
            get
            {
                return m_graphicsVolume;
            }
        }

        public BoundingBox Box
        {
            get
            {
                return m_boundingBox;
            }
        }

        #endregion

        #region Public Member Functions

        public CPlaneRenderObject(GraphicsDevice device, float width, float depth)
        {
            SetUpVertexBuffer(device, width, depth);
            SetUpIndexBuffer(device);
            SetBuffers(device);
        }

        public void Draw(GraphicsDevice device, Matrix m4World, Matrix m4View, Matrix m4Projection)
        {
            device.RenderState.DepthBufferEnable = true;
            device.RenderState.DepthBufferWriteEnable = true;

            //device.RenderState.FillMode = FillMode.WireFrame;

            device.VertexDeclaration = m_vertexDeclaration;

            device.Vertices[0].SetSource(m_vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);
            device.Indices = m_indexBuffer;

            device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, m_vertices.Length, 0, 2);
            //device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.PointList, m_vertices, 0, m_vertices.Length);
        }

        public void AddToBatch(CBatchManager batchManager, CRainbowXNA.CRenderInstance instance)
        {
            batchManager.Add(instance);
        }

        public CRainbowXNA.CRenderInstance CreateDefaultInstance(CRainbowXNA.RenderObjectHandleType handle, CRainbowXNA rainbow)
        {
            Trace.Assert(handle.RenderObject == this);
            return new CRainbowXNA.CRenderInstance(handle);
        }

        #endregion

        #region Protected Member Functions
        #endregion

        #region Private Member Functions

        private void SetUpVertexBuffer(GraphicsDevice device, float width, float depth )
        {
            m_vertices = new VertexPositionNormalTexture[2 * 2];

            //
            //  Back Left
            //
            m_vertices[0].Position = new Vector3(0, 0, depth);
            m_vertices[0].TextureCoordinate = new Vector2(0, 1);
            m_vertices[0].Normal = Vector3.Up;

            //
            //  Forward Left
            //
            m_vertices[1].Position = new Vector3(0, 0, 0);
            m_vertices[1].TextureCoordinate = new Vector2(0, 0);
            m_vertices[1].Normal = Vector3.Up;

            //
            //  Forward Right
            //
            m_vertices[2].Position = new Vector3(width, 0, 0);
            m_vertices[2].TextureCoordinate = new Vector2(1, 0);
            m_vertices[2].Normal = Vector3.Up;

            //
            //  Back Right
            //
            m_vertices[3].Position = new Vector3(width, 0, depth);
            m_vertices[3].TextureCoordinate = new Vector2(1, 1);
            m_vertices[3].Normal = Vector3.Up;

            m_boundingBox.Min = new Vector3(0.0f, -1.0f, 0.0f);
            m_boundingBox.Max = new Vector3(width, 1.0f, depth);

            m_graphicsVolume = BoundingSphere.CreateFromBoundingBox(m_boundingBox);
        }

        private void SetUpIndexBuffer(GraphicsDevice device)
        {
            m_indexes = new int[6];

            m_indexes[0] = 0;
            m_indexes[1] = 1;
            m_indexes[2] = 3;

            m_indexes[3] = 1;
            m_indexes[4] = 2;
            m_indexes[5] = 3;
        }

        private void SetBuffers(GraphicsDevice device)
        {
            m_vertexDeclaration = new VertexDeclaration(device, VertexPositionNormalTexture.VertexElements);
            m_vertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.SizeInBytes * m_vertices.Length, BufferUsage.WriteOnly);
            m_vertexBuffer.SetData<VertexPositionNormalTexture>(m_vertices);

            m_indexBuffer = new IndexBuffer(device, sizeof(int) * m_indexes.Length, BufferUsage.WriteOnly, IndexElementSize.ThirtyTwoBits);
            m_indexBuffer.SetData<int>(m_indexes);
        }

        #endregion
    }
}
